home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / fviewsrc.zip / UNZIP.C < prev    next >
C/C++ Source or Header  |  1993-01-04  |  14KB  |  546 lines

  1. /*--------------------------------------------------------------------------*/
  2. /* This is basically UNZIP.C by Samuel H. Smith. There have been several    */
  3. /* modifications to meet the needs of FVIEW, as opposed to a stand-alone    */
  4. /* program. Who can judge when source code has been so modified as to no    */
  5. /* longer belongs to the original person? So you better respect his copy-   */
  6. /* right. I still want to do more work on this thing. There's an AWFUL      */
  7. /* amount of global data here.                                              */
  8. /*                                                                          */
  9. /* Copyright 1989, Doug Boone                                               */
  10. /*--------------------------------------------------------------------------*/
  11.  
  12. #include    <stdio.h>
  13. #include    <stdlib.h>
  14. #include    <io.h>
  15. #ifndef TURBOC
  16. #include    <sys\types.h>
  17. #include    <malloc.h>
  18. #endif
  19. #include    <sys\stat.h>
  20. #include    <fcntl.h>
  21. #include    <string.h>
  22. #include    "archdr.h"
  23. #include    "unzip.h"
  24.  
  25.  
  26. int     unzip(char *,char *);
  27. int     loadup(void);
  28. int     read_bytes(unsigned *);
  29. int     load_bits(int);
  30. void    flushout(void);
  31. void    load_follower(void);
  32. void    reduced(void);
  33. void    clear_part(void);
  34. void    shrunk(void);
  35. int     get_file(char *);
  36. void    do_header(char *);
  37.  
  38.  
  39. /* Main entry point for this module */
  40.  
  41. int unzip(char *in_name,char *out_name)
  42. {
  43.  
  44.     bits_left = 0;
  45.     bitbuf = 0;
  46.     incnt = 0;
  47.     outpos = 0L;
  48.     outcnt = 0;
  49.     zipeof = 0;
  50.  
  51.  
  52.     inbuf = (byte *) malloc(INBUF_SIZE);
  53.     outbuf = (byte *) malloc(OUTBUF_SIZE);
  54.  
  55.     inptr = inbuf;
  56.     outptr = outbuf;
  57.     if ((inbuf == 0L ) || (outbuf == 0L )) {
  58.         fprintf(Log_fp,"Can't allocate buffers!\n");
  59.         return(1);
  60.         }
  61.     if ((in_handle = open(in_name,O_RDONLY|O_BINARY)) < 1) {
  62.         free(inbuf);
  63.         free(outbuf);
  64.         return(1);
  65.         }
  66.  
  67.     do_header(out_name);
  68.  
  69.     close(in_handle);
  70.     free(inbuf);
  71.     free(outbuf);
  72.     return(0);
  73. }
  74.  
  75. int loadup(void)
  76. {
  77.     int readsize;
  78.  
  79.     if (packed <= 0)
  80.         return incnt = 0;
  81.  
  82.     if (packed > INBUF_SIZE )
  83.         readsize = INBUF_SIZE ;
  84.     else
  85.         readsize = (int) packed;
  86.     incnt = read(in_handle, inbuf, readsize);
  87.  
  88.     packed -= incnt;
  89.     inptr = inbuf;
  90.     return incnt--;
  91. }
  92.  
  93. int read_bytes(unsigned *x)
  94. {
  95.     if (incnt-- == 0)
  96.         if (loadup() == 0)
  97.             return 0;
  98.     *x = *inptr++;
  99.     return 8;
  100. }
  101.  
  102.  
  103. int load_bits(register int bits)
  104. {
  105.  
  106.     unsigned temp;
  107.     register int result = bitbuf;
  108.     int sbits = bits_left;
  109.  
  110.     bits -= bits_left;
  111.  
  112.     bits_left = read_bytes(&bitbuf);
  113.     bits_left += read_bytes(&temp);
  114.     bitbuf |= (temp << 8);
  115.     if (bits_left == 0)
  116.     zipeof = 1;
  117.  
  118.     result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
  119.     bitbuf >>= bits;
  120.     bits_left -= bits;
  121.     return result;
  122. }
  123.  
  124. void flushout(void)
  125. {
  126.     write(out_handle, outbuf, outcnt);
  127.     outpos += outcnt;
  128.     outcnt = 0;
  129.     outptr = outbuf;
  130. }
  131.  
  132. void load_follower(void)
  133. {
  134.     register int x;
  135.     register int i;
  136.  
  137.     for (x = 255; x >= 0; x--) {
  138.         if (6 <= bits_left) {
  139.             Slen[x] = (int)(bitbuf & mask_bits[6]);
  140.             bitbuf >>= 6;
  141.             bits_left -= 6;
  142.             }
  143.         else
  144.             Slen[x] = load_bits(6);
  145.  
  146.         for (i = 0; i < Slen[x]; i++) {
  147.             if (8 <= bits_left) {
  148.                 followers[x][i] = (int)(bitbuf & mask_bits[8]);
  149.                 bitbuf >>= 8; bits_left -= 8;
  150.                 }
  151.             else
  152.                 followers[x][i] = load_bits(8);
  153.             } /* end of for(Slen[x]) loop */
  154.         } /* end of for(x) loop */
  155. }
  156.  
  157.  
  158.  
  159. void reduced(void)
  160. {
  161.     int     lchar;
  162.     int        i;
  163.     int        ix;
  164.     int     nchar;
  165.     int     ExState;
  166.     int     V;
  167.     int     Len;
  168.     int        offset;
  169.     int        follower;
  170.     int        bitsneeded;
  171.     int     factor;
  172.     long    op;
  173.  
  174.     factor = method - 1;
  175.     ExState = 0;
  176.     lchar = 0;
  177.     load_follower();
  178.  
  179.     while (((outpos + outcnt) < unpacked) && (!zipeof)) {
  180.         if (Slen[lchar] == 0) {
  181.             if (8 <= bits_left) {
  182.                 nchar = (int)(bitbuf & mask_bits[8]);
  183.                 bitbuf >>= 8;
  184.                 bits_left -= 8;
  185.                 }
  186.             else
  187.                 nchar = load_bits(8);
  188.             }
  189.         else {
  190.             if (1 <= bits_left) {
  191.                 nchar = (int)(bitbuf & mask_bits[1]);
  192.                 bitbuf >>= 1;
  193.                 bits_left -= 1;
  194.                 }
  195.             else
  196.                 nchar = load_bits(1);
  197.  
  198.             if (nchar != 0) {
  199.                 if (8 <= bits_left) {
  200.                     nchar = (int)(bitbuf & mask_bits[8]);
  201.                     bitbuf >>= 8;
  202.                     bits_left -= 8;
  203.                     }
  204.                 else
  205.                     nchar = load_bits(8);
  206.                 }
  207.             else  {
  208.                 bitsneeded = B_table[Slen[lchar]];
  209.                 if (bitsneeded <= bits_left) {
  210.                     follower = (int)(bitbuf & mask_bits[bitsneeded]);
  211.                     bitbuf >>= bitsneeded;
  212.                     bits_left -= bitsneeded;
  213.                     }
  214.                 else
  215.                     follower = load_bits(bitsneeded);
  216.                 nchar = followers[lchar][follower];
  217.                 }
  218.         }  /* This one is questionable! */
  219.  
  220.         switch (ExState) {
  221.  
  222.             case 0:
  223.                         if (nchar != DLE ) {
  224.                             *outptr++=nchar;
  225.                             if (++outcnt == OUTBUF_SIZE)
  226.                                 flushout();
  227.                             }
  228.                         else
  229.                         ExState = 1;
  230.                         break;
  231.  
  232.             case 1:
  233.                         if (nchar != 0) {
  234.                             V = nchar;
  235.                             Len = V & L_table[factor];
  236.                             if (Len == L_table[factor])
  237.                                 ExState = 2;
  238.                             else
  239.                                 ExState = 3;
  240.                             }
  241.                         else {
  242.                             *outptr++ = DLE;
  243.                             if (++outcnt == OUTBUF_SIZE )
  244.                                 flushout();
  245.                             ExState = 0;
  246.                             }
  247.                         break;
  248.  
  249.             case 2:
  250.                         Len += nchar;
  251.                         ExState = 3;
  252.                         break;
  253.  
  254.             case 3:        i = Len + 3;
  255.                         offset = (((V >> D_shift[factor]) &
  256.                             D_mask[factor]) << 8) + nchar + 1;
  257.                         op = outpos + outcnt - offset;
  258.  
  259.                         while ((op < 0L) && (i > 0)) {
  260.                             *outptr++=0;
  261.                             if (++outcnt==OUTBUF_SIZE )
  262.                                 flushout();
  263.                             op++;
  264.                             i--;
  265.                             } /* End of while((op<0L && (i>0)) */
  266.  
  267.                         ix = (int) (op % OUTBUF_SIZE );
  268.                         if ( (((long)(ix + i)) < OUTBUF_SIZE ) &&
  269.                             ((outcnt+i) < OUTBUF_SIZE ) ) {
  270.                                  memcpy(outptr,&outbuf[ix],i);
  271.                                  outptr += i;
  272.                                  outcnt += i;
  273.                                  }
  274.                         else {
  275.                             while (i--) {
  276.                                 *outptr++=outbuf[ix];
  277.                                 if (++outcnt==OUTBUF_SIZE )
  278.                                     flushout();
  279.                                 if (((long)++ix) >= OUTBUF_SIZE )
  280.                                     ix = 0;
  281.                                 }
  282.                             }
  283.  
  284.                         ExState = 0;
  285.                         break;        /* End of case 3 */
  286.             }        /* End of Switch statement */
  287.  
  288.         lchar = nchar;
  289.         }  /* End of WHILE loop */
  290.     return;
  291. }
  292.  
  293.  
  294. void clear_part(void)
  295. {
  296.     register int pr;
  297.     register int cd;
  298.  
  299.     for (cd = FIRST ; cd < free_ent; cd++)
  300.         prefix[cd] |= 0x8000;
  301.  
  302.     for (cd = FIRST ; cd < free_ent; cd++) {
  303.         pr = prefix[cd] & 0x7fff;    
  304.         if (pr >= FIRST )            
  305.             prefix[pr] &= 0x7fff;
  306.         }
  307.  
  308.  
  309.     for (cd = FIRST ; cd < free_ent; cd++)
  310.         if ((prefix[cd] & 0x8000) != 0)
  311.             prefix[cd] = -1;
  312.  
  313.  
  314.     cd = FIRST ;
  315.     while ((cd < maxcodemax) && (prefix[cd] != -1))
  316.         cd++;
  317.     free_ent = cd;
  318. }
  319.  
  320. void shrunk(void)
  321. {
  322.  
  323.     register int code;
  324.     register int stackp;
  325.     int finchar;
  326.     int oldcode;
  327.     int incode;
  328.  
  329.     maxcodemax = 1 << MAX_BITS ;
  330.     codesize = INIT_BITS ;
  331.     maxcode = (1 << codesize) - 1;
  332.     free_ent = FIRST ;
  333.     offset = 0;
  334.  
  335.     for (code = maxcodemax; code > 255; code--)
  336.         prefix[code] = -1;
  337.  
  338.     for (code = 255; code >= 0; code--) {
  339.         prefix[code] = 0;
  340.         suffix[code] = code;
  341.         }
  342.  
  343.     if (codesize <= bits_left) {
  344.         oldcode = (int)(bitbuf & mask_bits[codesize]);
  345.         bitbuf >>= codesize;
  346.         bits_left -= codesize;
  347.         }
  348.     else
  349.         oldcode = load_bits(codesize);
  350.  
  351.     if (zipeof)
  352.         return;
  353.     finchar = oldcode;
  354.  
  355.     *outptr++=finchar;
  356.     if (++outcnt==OUTBUF_SIZE )
  357.         flushout(); 
  358.  
  359.     stackp = HSIZE ;
  360.  
  361.     while (!zipeof) {
  362.         if (codesize <= bits_left) {
  363.             code = (int)(bitbuf & mask_bits[codesize]);
  364.             bitbuf >>= codesize;
  365.             bits_left -= codesize;
  366.             }
  367.         else
  368.             code = load_bits(codesize);
  369.  
  370.         if (zipeof)
  371.             return;
  372.  
  373.         while (code == CLEAR ) {
  374.             if (codesize <= bits_left) {
  375.                 code = (int)(bitbuf & mask_bits[codesize]);
  376.                 bitbuf >>= codesize;
  377.                 bits_left -= codesize;
  378.                 }
  379.             else
  380.                 code = load_bits(codesize);
  381.             /*}*/
  382.             switch (code) {
  383.  
  384.                 case 1:
  385.                             codesize++;
  386.                             if (codesize == MAX_BITS )
  387.                                 maxcode = maxcodemax;
  388.                             else
  389.                                 maxcode = (1 << codesize) - 1;
  390.                             break;
  391.  
  392.                 case 2:
  393.                             clear_part();
  394.                             break;
  395.                 }        /* End of switch(code) */
  396.  
  397.             
  398.             if (codesize <= bits_left) {
  399.                 code = (int)(bitbuf & mask_bits[codesize]);
  400.                 bitbuf >>= codesize;
  401.                 bits_left -= codesize;
  402.                 }
  403.             else
  404.                 code = load_bits(codesize);
  405.  
  406.             if (zipeof)
  407.                 return;
  408.             }        /* End of while(code == CLEAR) */
  409.  
  410.         incode = code;
  411.         if (prefix[code] == -1) {
  412.             stack[--stackp] = finchar;
  413.             code = oldcode;
  414.             }
  415.  
  416.  
  417.         while (code >= FIRST ) {
  418.             stack[--stackp] = suffix[code];
  419.             code = prefix[code];
  420.             }
  421.  
  422.         finchar = suffix[code];
  423.         stack[--stackp] = finchar;
  424.  
  425.         if ((HSIZE -stackp+outcnt) < OUTBUF_SIZE ) {
  426.             memcpy(outptr,&stack[stackp],HSIZE -stackp);
  427.             outptr += HSIZE -stackp;
  428.             outcnt += HSIZE -stackp;
  429.             stackp = HSIZE ;
  430.             }
  431.  
  432.         else while (stackp < HSIZE ) {
  433.             *outptr++=stack[stackp++];
  434.             if (++outcnt==OUTBUF_SIZE )
  435.                 flushout();
  436.             } 
  437.  
  438.         code = free_ent;
  439.         if (code < maxcodemax) {
  440.             prefix[code] = oldcode;
  441.             suffix[code] = finchar;
  442.  
  443.             do
  444.                 code++;
  445.                 while ((code < maxcodemax) && (prefix[code] != -1));
  446.  
  447.             free_ent = code;
  448.             }
  449.  
  450.         oldcode = incode;
  451.         }        /* End of while(!zipeof) */
  452.  
  453. }
  454.  
  455.  
  456. int get_file(char *dearc)
  457. {
  458.     unsigned b;
  459.  
  460.     if ((out_handle = open(dearc,O_RDWR|O_BINARY|O_CREAT,S_IREAD|S_IWRITE)) < 1 ) {
  461.         fprintf(Log_fp,"Can't create output: %s\n", dearc);
  462.         return 1;
  463.         }
  464.  
  465.     write(out_handle, "?", 1);
  466.     lseek(out_handle, 0L,SEEK_SET);
  467.  
  468.     switch (method) {
  469.  
  470.         case 0:        
  471.                     while (read_bytes(&b)) {
  472.                         *outptr++=b;
  473.                         if (++outcnt==OUTBUF_SIZE )
  474.                             flushout();
  475.                         } 
  476.                     break;
  477.  
  478.         case 1: 
  479.                     shrunk();
  480.                     break;
  481.  
  482.         case 2:
  483.         case 3:
  484.         case 4:
  485.         case 5: 
  486.                     reduced();
  487.                     break;
  488.  
  489.         default:
  490.                     fprintf(Log_fp,"Unknown compression method.\n");
  491.         }
  492.     if (outcnt > 0)
  493.         write(out_handle, outbuf, outcnt);
  494.     close(out_handle);
  495.     return(0);
  496. }
  497.  
  498.  
  499. void do_header(char *dearc)
  500. {
  501.     struct  ID_Hdr          *ID;
  502.     struct  Local_Hdr       *local;
  503.     char    *mbrname;
  504.     int        check;
  505.     char    *test;
  506.  
  507.     if ((test = strrchr(dearc,'\\')) == 0L )
  508.         test = dearc;
  509.     else
  510.         test++;
  511.  
  512.     ID = (struct ID_Hdr *) malloc(sizeof(struct ID_Hdr));
  513.     local = (struct Local_Hdr *) malloc(sizeof(struct Local_Hdr));
  514.     mbrname = (char *) malloc(80);
  515.  
  516.     do {
  517.         check = read(in_handle,(void *)ID,sizeof(struct ID_Hdr));
  518.         if (ID->Head_Type == LOCAL_HEADER) {
  519.             if ((check = read(in_handle,(void *)local,sizeof(struct Local_Hdr))) != -1) {
  520.                 memset(mbrname,EOS,80);
  521.                 check = read(in_handle,mbrname,local->name_length);
  522.                 lseek(in_handle,((long)local->Xfield_length),SEEK_CUR);
  523.  
  524.                 if (stricmp(test,mbrname) == 0) {
  525.                     packed = local->size_now;
  526.                     method = local->compression;
  527.                     unpacked = local->real_size;
  528.                     get_file(dearc);
  529.                     zipeof = 1;
  530.                     }
  531.                 else
  532.                     lseek(in_handle,local->size_now,SEEK_CUR);
  533.  
  534.                 }        /* End of one entry */
  535.             }        /* End of grabbing local directory entries */
  536.         else
  537.             check = -1;
  538.         } while(check >0 && !zipeof);        /* End of file */
  539.     free(local);
  540.     free(mbrname);
  541.     free(ID);
  542.     return;
  543. }
  544.  
  545.  
  546.